package utils

import (
	"fmt"
	"math/big"
	"reflect"
	"runtime"
	"strings"
	"time"

	"github.com/fatih/color"
	"github.com/shopspring/decimal"
)

// ErrorLog 错误日志
func ErrorLog(args ...interface{}) {
	pc, file, line, ok := runtime.Caller(1)
	if !ok {
		file = "unknown"
		line = 0
	}
	funcName := "unknown"
	if fn := runtime.FuncForPC(pc); fn != nil {
		funcName = simplifyFuncName(fn.Name())
	}
	// 彩色样式
	border := color.New(color.FgRed).SprintFunc()
	label := color.New(color.FgHiRed).SprintfFunc()
	value := color.New(color.FgHiWhite).SprintFunc()
	level := color.New(color.FgRed, color.Bold).SprintFunc()
	// 打印格式化日志
	fmt.Println(border("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
	fmt.Printf("%s %s\n", label("[LEVEL]"), level("ERROR"))
	fmt.Printf("%s %s\n", label("[FILE] "), value(file))
	fmt.Printf("%s %d\n", label("[LINE] "), line)
	fmt.Printf("%s %s\n", label("[FUNC] "), value(funcName))
	fmt.Printf("%s %s\n", label("[MESSAGE]"), value(fmt.Sprint(args...)))
	fmt.Println(border("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
}

// InfoLog 格式化美观日志（多行输出）
func InfoLog(args ...interface{}) {
	pc, file, line, ok := runtime.Caller(1)
	if !ok {
		file = "unknown"
		line = 0
	}
	funcName := "unknown"
	if fn := runtime.FuncForPC(pc); fn != nil {
		funcName = simplifyFuncName(fn.Name())
	}
	// 彩色样式
	border := color.New(color.FgHiBlue).SprintFunc()
	label := color.New(color.FgCyan).SprintfFunc()
	value := color.New(color.FgHiWhite).SprintFunc()
	level := color.New(color.FgGreen, color.Bold).SprintFunc()
	// 打印格式化日志
	fmt.Println(border("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
	fmt.Printf("%s %s\n", label("[LEVEL]"), level("INFO"))
	fmt.Printf("%s %s\n", label("[FILE] "), value(file))
	fmt.Printf("%s %d\n", label("[LINE] "), line)
	fmt.Printf("%s %s\n", label("[FUNC] "), value(funcName))
	fmt.Printf("%s %s\n", label("[MESSAGE]"), value(fmt.Sprint(args...)))
	fmt.Println(border("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"))
}

// 简化函数名（去除路径）
func simplifyFuncName(full string) string {
	if idx := strings.LastIndex(full, "/"); idx != -1 {
		return full[idx+1:]
	}
	return full
}

func FormatDate(t any) string {
	switch v := t.(type) {
	case *time.Time:
		if v == nil || v.IsZero() {
			return ""
		}
		return v.Format("2006-01-02")
	case time.Time:
		if v.IsZero() {
			return ""
		}
		return v.Format("2006-01-02")
	default:
		return ""
	}
}

type BatchMath struct {
	value         decimal.Decimal
	precision     int32
	isInitialized bool
}

func NewBatchMath(d uint) *BatchMath {
	return &BatchMath{
		precision:     int32(d),
		value:         decimal.Zero,
		isInitialized: false,
	}
}

func (bm *BatchMath) Add(data ...any) *BatchMath {
	for _, num := range data {
		numDecimal := ToDecimal(num)
		if !bm.isInitialized {
			bm.value = numDecimal
			bm.isInitialized = true
		} else {
			bm.value = bm.value.Add(numDecimal)
		}
	}
	return bm
}

func (bm *BatchMath) Sub(data ...any) *BatchMath {
	for _, num := range data {
		numDecimal := ToDecimal(num)
		if !bm.isInitialized {
			bm.value = numDecimal
			bm.isInitialized = true
		} else {
			bm.value = bm.value.Sub(numDecimal)
		}
	}
	return bm
}

func (bm *BatchMath) Mul(data ...any) *BatchMath {
	for _, num := range data {
		numDecimal := ToDecimal(num)
		if !bm.isInitialized {
			bm.value = numDecimal
			bm.isInitialized = true
		} else {
			bm.value = bm.value.Mul(numDecimal)
		}
	}
	return bm
}

func (bm *BatchMath) Div(data ...any) *BatchMath {
	beforeBm := *bm
	for _, num := range data {
		numDecimal := ToDecimal(num)
		if numDecimal.IsZero() {
			return &beforeBm
		}
		if !bm.isInitialized {
			bm.value = numDecimal
			bm.isInitialized = true
		} else {
			bm.value = bm.value.Div(numDecimal)
		}
	}
	return bm
}

func (bm *BatchMath) Value() decimal.Decimal {
	return bm.value.Round(bm.precision)
}

func (bm *BatchMath) Float64() float64 {
	return bm.value.Round(bm.precision).InexactFloat64()
}

// ToDecimal 将任意类型转换为 decimal.Decimal
func ToDecimal(value any) decimal.Decimal {
	switch v := value.(type) {
	case int, int8, int16, int32, int64:
		return decimal.NewFromFloat(float64(reflect.ValueOf(v).Int()))
	case uint, uint8, uint16, uint32, uint64:
		return decimal.NewFromFloat(float64(reflect.ValueOf(v).Uint()))
	case float32, float64:
		return decimal.NewFromFloat(reflect.ValueOf(v).Float())
	case string:
		fromString, err := decimal.NewFromString(v)
		if err != nil {
			return decimal.Decimal{}
		}
		return fromString
	case *big.Int:
		return decimal.NewFromBigInt(v, 0)
	case *big.Rat:
		return decimal.NewFromBigRat(v, 0)
	case decimal.Decimal:
		return v
	default:
		return decimal.Decimal{}
	}
}

// ParseDateTime 尝试解析各种常见日期字符串为 time.Time
// 支持格式：
//   - 2006-01-02 15:04:05
//   - 2006-01-02 15:04
//   - 2006-01-02
//   - 2006/01/02 15:04:05
//   - 2006/01/02
func ParseDateTime(s string) time.Time {
	if s == "" {
		return time.Time{}
	}

	formats := []string{
		"2006-01-02 15:04:05",
		"2006-01-02 15:04",
		"2006-01-02",
		"2006/01/02 15:04:05",
		"2006/01/02",
	}

	for _, layout := range formats {
		if t, err := time.ParseInLocation(layout, s, time.Local); err == nil {
			return t
		}
	}
	return time.Time{}
}

// ParseDate 尝试解析多种日期格式
func ParseDate(dateStr string) *time.Time {
	dateStr = strings.TrimSpace(dateStr)

	// 把中文“年”“月”“日”替换成分隔符
	dateStr = strings.ReplaceAll(dateStr, "年", "-")
	dateStr = strings.ReplaceAll(dateStr, "月", "-")
	dateStr = strings.ReplaceAll(dateStr, "日", "")

	// 常见日期格式列表
	formats := []string{
		"2006-1-2",
		"2006/1/2",
		"2006.1.2",
		"2006-01-02",
		"2006/01/02",
		"2006.01.02",
	}

	var t time.Time
	var err error
	for _, f := range formats {
		t, err = time.ParseInLocation(f, dateStr, time.Local)
		if err == nil {
			return &t
		}
	}
	return nil
}
